using System;
using System.Xml;
using System.Web;

namespace umlungu.engineX.webserviceX {
	/// <summary>
	/// Defintion class for umlungu engineX Gatekeep services.
	///	This class instantiated in the global.asax and stored as an application variable 
	/// </summary>
	public class x_service {
		#region Invisible properties
		/// <summary>
		/// Local properties
		/// </summary>
		private string xdefFile;
		private XmlDocument xdefDoc;
		#endregion

		#region Visible properties
		/// <summary>
		/// Accessor properties
		/// </summary>
		public XmlDocument Defintion	{ get { return xdefDoc; }}
		#endregion

		#region Constructors/Destructors
		/// <overloads>Constructor</overloads>
		/// <summary>Default constructor</summary>
		/// <param name="srv">The Web service server object</param>
		/// <param name="what">The name of the service (definition file)</param>
		public x_service(HttpServerUtility srv, string what) {
			xdefDoc = new XmlDocument();
			xdefFile = srv.MapPath(what + ".xml");
			xdefDoc.Load(xdefFile);
		}
		/// <summary>Constructor description</summary>
		/// <param name="what">The name of the service (definition file)</param>
		public x_service(string what) {
			xdefFile = what;
			xdefDoc = new XmlDocument();
			xdefDoc.Load(xdefFile);
		}
		#endregion

		#region Public methods
		/// <summary>
		/// Gets the fully qualified path of the service definition file.
		/// </summary>
		public string GetDefintionFile() {
			return(xdefFile);
		}
		/// <summary>
		/// Gets the module identifier
		/// </summary>
		public string GetId() {
			XmlElement thisMod = (XmlElement)xdefDoc.SelectSingleNode("//modules");
			return(thisMod.GetAttribute("id"));
		}
		/// <summary>
		/// Gets the definition of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public XmlNode GetDefintion(string methodName) {
			return(xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']"));
		}
		/// <summary>
		/// Gets the return element of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public string GetReturn(string methodName) {
			return(xdefDoc.SelectSingleNode("//module[method/@name='" + methodName + "']/return").InnerXml);
		}
		/// <summary>
		/// Gets the module name of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public string GetModule(string methodName) {
			XmlNode thisMod = xdefDoc.SelectSingleNode("//module[method/@name='" + methodName + "']/@name");
			return(thisMod.InnerText);
		}
		/// <summary>
		/// Gets the identifier of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public string GetMethodId(string methodName) {
			XmlElement thisMod = (XmlElement)xdefDoc.SelectSingleNode("//module[method/@name='" + methodName + "']");
			return(thisMod.GetAttribute("id"));
		}
		/// <summary>
		/// Gets the default result type of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public string GetResultType(string methodName) {
			XmlNode thisRes = xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/result[@default='yes']/@type");
			return(thisRes.Value);
		}
		/// <overloads>Gets the result value of the named method</overloads>
		/// <summary>
		/// The default result type
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public string GetResult(string methodName) {
			XmlNode thisRes = xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/result[@default='yes']");
			return(thisRes.InnerXml);
		}
		/// <summary>
		/// A specified result type
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		/// <param name="resultType">The result type</param>
		public string GetResult(string methodName, string resultType) {
			XmlNode thisRes = xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/result[@type='" + resultType + "']");
			return(thisRes.InnerXml);
		}
		/// <summary>
		/// Gets the result type = set of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		/// <param name="parentName">The parent name</param>
		public string GetResultSet(string methodName, out string parentName ) {
			XmlNode thisRes = xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/result[@type='set' or @type='csv']");
			XmlNode thisPar = thisRes.SelectSingleNode("@parent");
			parentName = (thisPar == null) ? "" : thisPar.InnerText;
			return(thisRes.InnerXml);
		}
		/// <summary>
		/// Gets the result node of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		/// <param name="resultType">The result type</param>
		public XmlNode GetResultNode(string methodName, string resultType) {
			XmlNode thisRes = xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/result[@type='" + resultType + "']");
			return(thisRes);
		}
		/// <summary>
		/// Gets the Call type of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public string GetCall(string methodName) {
			XmlElement thisCall = (XmlElement)xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/call");
			return((thisCall == null)? "" : thisCall.GetAttribute("type"));
		}
		/// <overloads>Gets the inputs of the named method</overloads>
		/// <summary>
		/// Gets all the inputs of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		/// <returns>An XmlNodeList of "parameter" elements</returns>
		public XmlNodeList GetInputs(string methodName) {
			return xdefDoc.SelectNodes(String.Concat("//module/method[@name='", methodName, "']/call/input/parameter"));
		}
		/// <summary>
		/// Gets the inputs of the named method of a type
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		/// <param name="inputType">The type of input (string, int, output)</param>
		/// <returns>An XmlNodeList of "parameter" elements</returns>
		public XmlNodeList GetInputs(string methodName, string inputType) {
			return xdefDoc.SelectNodes(String.Concat("//module/method[@name='", methodName, "']/call/input/parameter[@type='", inputType, "']"));
		}
		/// <overloads>Gets the stored procedure name of the named method</overloads>
		/// <summary>
		/// Method specified by name
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public string GetProcedure(string methodName) {
			XmlElement thisProc = (XmlElement)xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/call[@type='sproc']");
			return((thisProc == null)? "" : thisProc.GetAttribute("name"));
		}
		/// <summary>
		/// Method specified by node
		/// </summary>
		/// <param name="xdef">The defintion node of the method in the definition file</param>
		public string GetProcedure(XmlNode xdef) {
			XmlElement thisProc = (XmlElement)xdef.SelectSingleNode("call[@type='sproc']");
			return((thisProc == null)? "" : thisProc.GetAttribute("name"));
		}
		/// <summary>
		/// Gets the result type = exception of the named method
		/// </summary>
		/// <param name="methodName">The name of the method in the definition file</param>
		public XmlNode GetException(string methodName) {
			return(xdefDoc.SelectSingleNode("//module/method[@name='" + methodName + "']/result[@type='exception']"));
		}
		/// <summary>
		/// Gets all the errors defined in the web service definition file
		/// </summary>
		public string GetErrors() {
			XmlElement newerr, newmeth;
			XmlDocument xErrs = new XmlDocument();
			xErrs.LoadXml("<errors/>");
			XmlNode root = xErrs.SelectSingleNode("//errors");
			foreach (XmlNode thismeth in xdefDoc.SelectNodes("//module/method")) {
				newmeth = xErrs.CreateElement("method");
				newmeth.SetAttribute("name", thismeth.SelectSingleNode("@name").InnerText);
				foreach (XmlNode thiserr in thismeth.SelectNodes("result[@type='error' or @type='exception']")) {
					newerr = xErrs.CreateElement("error");
					newerr.SetAttribute("code", thiserr.SelectSingleNode("@value").InnerText);
					newerr.InnerText = thiserr.InnerText;
					newmeth.AppendChild(newerr);
				}
				root.AppendChild(newmeth);
			}
			return(root.OuterXml);
		}
		#endregion
		
		#region Protected methods
		#endregion
				
		#region Private methods
		#endregion
	}
}
